#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); //设置LCD1602设备地址0x27，16列2行

// 滚动文本（长度≥20字符，确保能滚动；末尾加空格过渡）
String scrollText1 = "I like arduino ! 2025 is coming~ Let's code !  O(n_n)O         ";
// 第二行固定文本
String fixedText2 = "welcome to 2025";

void setup() {
  lcd.init();
  lcd.backlight();
  
  // 初始化第二行（只打印1次，固定不闪）
  lcd.setCursor(0, 1);
  lcd.print(fixedText2);
  
  // 初始化第一行：先打印16个空格清空第一行残留，再显示初始文本
  lcd.setCursor(0, 0);
  lcd.print("                "); // 16个空格，覆盖第一行所有列
  lcd.setCursor(0, 0);
  lcd.print(scrollText1.substring(0, 16)); // 显示第一行初始文本
}

void loop() {
  static int i = 1; // 从1开始，避免初始重复；static变量不会重置
  
  // 1. 生成当前要显示的第一行（确保截取后是16个字符，不会为空）
  String currentLine1 = scrollText1.substring(i); // 从i开始取后面所有字符
  currentLine1 += scrollText1.substring(0, i);    // 拼接前面0~i-1的字符
  currentLine1 = currentLine1.substring(0, 16);   // 强制截取16个字符（关键）
  
  // 2. 局部刷新第一行（不闪屏核心：先清当前行，再打印新文本）
  lcd.setCursor(0, 0);
  lcd.print("                "); // 用16个空格覆盖第一行，避免残留
  lcd.setCursor(0, 0);
  lcd.print(currentLine1);
  
  // 3. 滚动步数更新（滚到末尾重置，循环滚动）
  i++;
  if (i >= scrollText1.length()) { // 当i超过文本长度，回到开头
    i = 0;
  }
  
  delay(250); // 速度适中，无闪屏（150-200ms均可）
}